<?php
/**
* File holding the controller class
*
* @author       Fabrice Douteaud <clearbudget@douteaud.com>
* @package      framework
* @access       public
*/

/***********************************************************************

  Copyright (C) 2008  Fabrice douteaud(clearbudget@douteaud.com)

    This file is part of ClearBudget.

    ClearBudget is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    

    ClearBudget is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ClearBudget.  If not, see <http://www.gnu.org/licenses/>.

************************************************************************/

/**
* Class managing the flow of event from a given request. It controls the actions
* that are requested and build the output message.
* 
* this is the applicaton controller.
* 
* @author       Fabrice Douteaud <clearbudget@douteaud.com>
* @package      framework
* @access       public
*/
class class_controller {
	/**
	* @var object Hold the instance of the current class
	* @access private
	* @static	
	*/
  private static $_instance = null;
  /**
	* @var string The text to be output
	* @access private
	* @static	
	*/
  private static $output = '';
 	/**
	* @var boolean A flag to tell if the output should be json encoded
	* @access private
	* @static	
	*/
  private static $json = false;
  
  
  /**  
	* Check if the user should be logged in
	* 
	* If the site require to be logged in, then it checks if the user is logged in.
	* If not, redirect him to the login page.	
	*	
	* @return void
	* @access private
	* @static	
	*/
  private static function controlSiteAccess() {
    // if we are asked to secure the access, we do it now
    if(class_settings::$secureAccess === '1' && !class_context::isUserLoggedIn()) {
      // save the requested page if not present yet
      if(!isset($_REQUEST['backAction'])) $_REQUEST['backAction'] = class_context::$action;
      // set the next action to be the login page
      class_context::$action = 'login';
      class_context::$snippet = 'login';
      }
    }
  
	/**
	* Performs the requested action from the context object 
	*
	* Multiple action file might be loaded in a loop. One action might set a next action to be called in the context.	
	*
	* @return void
	* @access public
	* @static	
	*/		
  public static function doAction() {
    // we always check if the application is ready first
    self::applicationReady();
    
    // we always check if the application should be password protected
    self::controlSiteAccess();
    
    // load the property key object to perform translation
    $keys = class_propertyKey::getInstance();
    
    // load the action(s) needed
    // this is a loop since an action can require a next action to be loaded
    do {
      // preset the next action to be false - prevents looping for ever :-)
      class_context::$nextAction = false;
      // prepare the path to be included
      $actionPath = 'actions'.DIRECTORY_SEPARATOR.class_context::$action.'.php';
      // if file does not exist, we simply continue
      if(file_exists($actionPath)) {
        // includes the files (i.e.: execute it)
        include($actionPath);
        class_debug::addMsg(__FILE__, 'loading of "'.$actionPath.'" done', DEBUGINFO);
        }
      else {
        class_debug::addMsg(__FILE__, 'loading of "'.$actionPath.'" failed', DEBUGINFO);
        break;
        }
      // if next action is set, we override the context action
      if(class_context::$nextAction !== false) class_context::$action = class_context::$nextAction;
      }
    while(class_context::$nextAction !== false);
    
    // now load the snippet output
    // build up the path to the snippet
    $snippetPath = 'snippets'.DIRECTORY_SEPARATOR.class_context::$snippet.'.php';
    // check snippet existence and load it
    if(file_exists($snippetPath)) {
      ob_start();
      include($snippetPath);
      self::$output = ob_get_contents();
      ob_end_clean();
      class_debug::addMsg(__FILE__, 'loading "'.$snippetPath.'" done', DEBUGINFO);
      }
    else {
      class_debug::addMsg(__FILE__, 'loading of "'.$snippetPath.'" failed', DEBUGINFO);
      }
    }

  /**
	* Render the output when in AJAX mode 
	*
	* Ajax mode is dictated from the context as it is a parameter in the query.
	* This function checks if the output is json encoded as to not output debug information.	
	*
	* @return void
	* @access private
	* @static	
	*/		
  private static function renderAjax() {
    echo self::$output;
    // prevent the debugger to output data if in JSON unless the debugger is set to log its output
    if(!self::$json || !DEBUGDISPLAYMSG) class_debug::displayMsg();
    }
  
  /**
	* Render the output 
	*
	* Renders the main template page.	
	*
	* @return void
	* @access private
	* @static	
	*/		
  private static function renderGeneric() {
    // load the property key object to perform translation
    $keys = class_propertyKey::getInstance();
    ob_start();
    include("style/index.php");
    $output =  ob_get_contents();
    ob_end_clean();
    echo $output;
    }
  
  /**
	* Master function to render the output 
	*
	* Switch the rendering between Ajax and non Ajax calls known from the context	
	*
	* @return void
	* @access public
	* @static	
	*/		
  public static function render() {
    // if in AJAX mode, echo of the raw action ouput
    // if not, load the default template page
    if(class_context::$ajax) {
      self::renderAjax();
      }
    else {
      self::renderGeneric();
      }
    }
  
  /**
	* Performs the requested action from the context object 
	*
	* Multiple action file might be loaded in a loop. One action might set a next action to be called in the context.	
	*
	* @return void
	* @access public
	* @static	
	*/		
  public static function applicationReady() {
    // check if the application has been setup correctly
    if(class_settings::setupDone()) {
      return true;
      }
    else {
      class_controller::sendRedirectTo('setup.php');
      }
    }

  /**
	* Sends the HTTP headers to force the user agent to not cache 
	*		
	* @return void
	* @access public
	* @static	
	*/
  public static function sendNoCacheHeader() {
    // cache control: no cache
    header("Cache-Control: no-cache");
    }
  
  /**
	* Sends the HTTP headers to force the user agent to redirect 
	*	
	* @param string URL the URL to redirect to (can be relative or absolute)	
	* @return void
	* @access public
	* @static	
	*/
  public static function sendRedirectTo($URL = null) {
    // prevent redirecting to nothing
    if($URL === null) return;
    // send header redirect
    header("Location: ".$URL);
    die();
    }
  
  /**
	* Provide an instance of the current class 
	*	
	* Implementation of the singleton pattern
	*   		
	* @return object An instance of this class
	* @access public
	* @static	
	*/  
  public static function getInstance() {
    if(is_null(self::$_instance)) {
      self::$_instance = new self();
      }
    return self::$_instance;
    } // getInstance()

  /**
	* class constructor 
	*	
	* access to this class is private as to implement the singleton pattern
	*   	
	* @return void
	* @access private
	*/
  private function __construct() {
    } // __construct()
  }
?>